#ifndef JSONRPCREQUEST_H
#define JSONRPCREQUEST_H

#include "JsonRpcMessage.h"
#include <QString>
#include <QVariant>
#include <QJsonObject>
#include <QJsonArray>

/**
 * @brief JSON-RPC 2.0 Request message class
 * 
 * This class represents a JSON-RPC 2.0 request message with method name and optional parameters.
 * The JSON object store in this class looks like:
 * ====================================
 * |  {                              |
 * |    jsonrpc:"2.0";               |
 * |    id: string | number;         |
 * |    method: string;              |
 * |    params?: {                   |
 * |      [key: string]: unknown;    |
 * |    }                            |
 * |  }                              |
 * ====================================
 */
class JsonRpcRequest : public JsonRpcMessage
{
public:
    /**
     * @brief Construct a new JsonRpcRequest object
     */
    JsonRpcRequest();

    /**
     * @brief Construct a new JsonRpcRequest object with method name
     * @param method - The method name to call
     */
    explicit JsonRpcRequest(const QVariant& id);

    /**
     * @brief Construct a new JsonRpcRequest object with method name and ID
     * @param method - The method name to call
     * @param id - The request ID (can be QString or numeric)
     */
    JsonRpcRequest(const QVariant& id, const QString& method);

    /**
     * @brief Construct a new JsonRpcRequest object with method name, parameters and ID
     * @param method - The method name to call
     * @param params - The method parameters, must be QJsonArray
     * @param id - The request ID (can be QString or numeric)
     */
    JsonRpcRequest(const QVariant& id, const QString& method, const QJsonObject& params);

    /**
     * @brief Destroy the JsonRpcRequest object
     */
    virtual ~JsonRpcRequest();

    /**
     * @brief Get the method name
     * @return QString - The method name
     */
    QString method() const;

    /**
     * @brief Set the method name
     * @param method - The method name to call
     */
    void setMethod(const QString& method);

    /**
     * @brief Get the method parameters
     * @return QVariant - The parameters (can be QJsonArray or QJsonObject)
     */
    QJsonObject params() const;

    /**
     * @brief Set the method parameters
     * @param params - The parameters (can be QJsonArray or QJsonObject)
     */
    void setParams(const QJsonObject& params);

    /**
     * @brief Check if the request has parameters
     * @return bool - True if parameters are present, false otherwise
     */
    bool hasParams() const;

    /**
     * @brief Convert the request to JSON object
     * @return QJsonObject - The JSON representation of the request
     */
    QJsonObject toJson() const override;

    /**
     * @brief Create JsonRpcRequest from JSON object
     * @param json - The JSON object to parse
     * @param ok - Optional pointer to store parsing success status
     * @return JsonRpcRequest - The parsed request object
     */
    static JsonRpcRequest fromJson(const QJsonObject& json, bool* ok = nullptr);

    /**
     * @brief Validate the request structure
     * @return bool - True if request is valid, false otherwise
     */
    bool isValid() const override;

private:
    QString mMethod;
    QJsonObject mParams;
};

#endif // JSONRPCREQUEST_H
